package main

import "fmt"

/**
 * Go语言接口教学示例
 * 接口是Go语言中实现多态的核心机制
在Go语言中，接口是一种类型，它定义了一组方法签名。
任何实现了这些方法的类型都可以被赋值给该接口类型的变量。
这就是Go语言实现多态的方式。
*/

// 定义一个接口Human，包含一个Say方法
type Human interface {
	Say() // 接口方法声明，只有方法签名没有实现
}

// 定义两个结构体类型
type Woman struct {
	name string
}

type Man struct {
	name string
}

// Human接口定义了一个Say()方法。
// Man和Woman类型都实现了Say()方法，因此它们都隐式地实现了Human接口。
// 当你将一个Man或Woman类型的实例赋值给Human类型的变量时，Go语言会自动识别这种隐式实现关系，因此可以接受。

// Woman类型实现Human接口的Say方法
func (w *Woman) Say() {
	fmt.Printf("我是%s，我是女性\n", w.name)
}

// Man类型实现Human接口的Say方法
func (m *Man) Say() {
	fmt.Printf("我是%s，我是男性\n", m.name)
}

// 多态函数，可以接受任何实现了Human接口的类型
func introduce(h Human) {
	h.Say()
}

func PrintValue(v interface{}) {
	fmt.Println(v)
}

func main() {
	//interface{} 是 Go 语言中的空接口类型（empty interface）。
	// 它是所有接口类型中最“空”的一个，不包含任何方法
	//Go 语言中所有类型都至少实现了空接口 ，因此任何值都满足空接口。
	PrintValue(123)                          // 传入 int
	PrintValue("hello")                      // 传入 string
	PrintValue(true)                         // 传入 bool
	PrintValue([]int{1, 2})                  // 传入切片
	PrintValue(struct{ name string }{"Tom"}) // 传入结构体

	// 创建实例
	alice := &Woman{name: "Alice"}
	bob := &Man{name: "Bob"}

	// 直接调用方法
	alice.Say()
	bob.Say()

	// 通过接口调用
	var h Human
	h = alice
	h.Say()
	h = bob
	h.Say()

	// 使用多态函数
	introduce(alice)
	introduce(bob)
}
